from PIL import Image, ImageDraw, ImageFont
import os
import textwrap
import platform
import zipfile

# --- 配置 ---
# 字体路径：自动适配Windows/macOS/Linux系统，若自定义路径需替换下方对应值
SYSTEM = platform.system()
if SYSTEM == "Windows":
    FONT_PATH = "C:/Windows/Fonts/simhei.ttf"  # Windows默认黑体
elif SYSTEM == "Darwin":  # macOS
    FONT_PATH = "/Library/Fonts/Songti.ttc"  # macOS默认宋体
else:  # Linux
    FONT_PATH = "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc"  # 文泉驿正黑

OUTPUT_DIR = "../add_text/pomeranian_reports"
ZIP_PATH = "../add_text/pomeranian_reports/pomeranian_reports.zip"

os.makedirs(OUTPUT_DIR, exist_ok=True)

# 报表尺寸 (3:4 比例)
WIDTH, HEIGHT = 768, 1024
BACKGROUND_COLOR = (255, 255, 255)  # 白色背景
TEXT_COLOR = (0, 0, 0)  # 黑色文字
TITLE_COLOR = (139, 0, 0)  # 深红色标题

# 字体设置（添加异常捕获，确保兼容无对应字体的系统）
try:
    FONT_TITLE = ImageFont.truetype(FONT_PATH, 40)
    FONT_SUBTITLE = ImageFont.truetype(FONT_PATH, 30)
    FONT_TEXT = ImageFont.truetype(FONT_PATH, 22)
    FONT_TABLE = ImageFont.truetype(FONT_PATH, 20)
except IOError:
    FONT_TITLE = ImageFont.load_default(size=40)
    FONT_SUBTITLE = ImageFont.load_default(size=30)
    FONT_TEXT = ImageFont.load_default(size=22)
    FONT_TABLE = ImageFont.load_default(size=20)

# 文本区域设置
MARGIN = 40
TEXT_WIDTH = WIDTH - 2 * MARGIN
LINE_HEIGHT = 30  # 文本行高
TABLE_ROW_HEIGHT = 50  # 表头默认高度

# --- 文章内容分段 ---
article_sections = [
    {"type": "title", "content": "博美犬的非毛色区别与分类"},
    {"type": "subtitle", "content": "一、品种起源与官方分类"},
    {"type": "text",
     "content": "博美犬（Pomeranian）属于尖嘴犬系（Spitz）家族，是其中体型最小的犬种。它的祖先是体型较大的德国狐狸犬（German Spitz），在国际犬业联盟（FCI）的标准中，博美犬被归类为德国狐狸犬的一种。"},
    {"type": "subtitle", "content": "官方体型标准"},
    {"type": "table", "header": ["机构", "理想体重范围", "备注"], "data": [
        ["AKC", "3-7 磅 (约 1.4-3.2 公斤)", "4-6 磅 (约 1.8-2.7 公斤) 被认为是理想的展示体型。"],
        ["KC", "4-5 磅 (约 1.8-2.3 公斤)", "强调紧凑、短背的体型。"]
    ], "cols": [0.2, 0.3, 0.5]},
    {"type": "text", "content": "博美犬偶尔会出现“返祖现象”，即体型远大于标准，这通常是由于其祖先德国狐狸犬的基因表达所致。这种体型较大的博美犬虽然不符合犬展标准，但仍是纯种博美犬。"},
    {"type": "subtitle", "content": "二、血系区别：英系（哈多利系）与美系"},
    {"type": "text",
     "content": "在博美犬的繁殖和爱好者群体中，最常被提及的分类是英系博美（English Pomeranian）和美系博美（American Pomeranian）。这种区别并非官方品种分类，而是基于不同国家繁殖者对品种标准的侧重和发展方向所形成的血系风格差异。"},
    {"type": "table", "header": ["特征", "英系博美 (哈多利系)", "美系博美"], "data": [
        ["脸部", "小巧秀美，嘴小微翘", "甜美圆润，俗称“泰迪熊脸”"],
        ["体型", "短背、紧凑，呈方形", "体型略大，呈长方形"],
        ["被毛", "毛质稍具波纹状，刚硬有光泽", "毛质呈绒状，毛量极其丰富"],
        ["风格", "更接近传统风格", "更符合玩赏犬的可爱风格"]
    ], "cols": [0.2, 0.4, 0.4]},
    {"type": "text", "content": "两种血系最本质的区别在于繁殖者对品种标准的侧重不同。血统纯正的哈多利系博美犬因其精致的品相，常被赞誉为博美犬中的珍品。"},
    {"type": "subtitle", "content": "三、非毛色特征的区别"},
    {"type": "subtitle", "content": "1. 头部与五官"},
    {"type": "text", "content": "眼睛应为中等大小，杏仁形，颜色深，眼神活泼。耳朵小而直立，呈三角形，位置高，不应过大。口吻适中，不宜过长（像狐狸）或过短（影响呼吸）。"},
    {"type": "subtitle", "content": "2. 被毛结构"},
    {"type": "text", "content": "博美犬的被毛是双层被毛：底毛（柔软、浓密）和外层被毛（粗硬、长而直）。被毛的丰厚度和质地是衡量一只博美犬品质的关键。毛量不足、毛质过软或过于丝滑都被视为缺陷。"},
    {"type": "subtitle", "content": "3. 步态与气质"},
    {"type": "text", "content": "步态应轻快、自由、充满活力。气质上，博美犬是一种紧凑、短背、活跃的玩赏犬。它们聪明、好奇、警惕性高，具有看家犬的本能。"},
    {"type": "text",
     "content": "总结：博美犬的魅力在于其多样的毛色，但其品种的深度则体现在其严谨的品种标准、独特的血系风格和非毛色特征上。无论是追求英系的紧凑方正，还是偏爱美系的圆润甜美，了解这些区别能帮助主人更好地欣赏和选择一只符合自己心意的博美犬。"}
]


# --- 辅助函数 ---
def get_text_size(draw, text, font):
    """使用 textbbox 精准获取文本尺寸 (width, height)"""
    bbox = draw.textbbox((0, 0), text, font=font)
    return bbox[2] - bbox[0], bbox[3] - bbox[1]


def draw_text_with_wrap(draw, text, x, y, font, max_width, color=TEXT_COLOR):
    """绘制自动换行文本（中英文自适应，英文整词换行，中文不拆字）"""
    # 纯英文文本：整词换行，禁止拆分单词
    if all(ord(c) < 128 for c in text):
        # 按字体大小估算每行单词数，适配英文排版
        chars_per_line = int(max_width / (font.size * 0.6))
        lines = textwrap.wrap(
            text,
            width=chars_per_line,
            break_long_words=False,  # 禁止拆分长单词
            break_on_hyphens=False  # 禁止在连字符处换行
        )
    # 含中文文本：以中文宽度为基准，英文可拆分（避免中文排版错乱）
    else:
        chinese_width, _ = get_text_size(draw, "中", font)
        chars_per_line = int(max_width / chinese_width) - 1  # 减1预留安全间距
        lines = textwrap.wrap(text, width=chars_per_line, break_long_words=True)

    current_y = y
    for line in lines:
        # 检查当前行是否溢出，溢出则返回None提示换页
        if current_y + LINE_HEIGHT > HEIGHT - MARGIN:
            return None
        draw.text((x, current_y), line, font=font, fill=color)
        current_y += LINE_HEIGHT
    return current_y


def draw_table(draw, header, data, x, y, cols_ratio):
    """绘制表格（中英文自适应换行，表头居中，单元格垂直居中）"""
    col_widths = [int(ratio * TEXT_WIDTH) for ratio in cols_ratio]
    current_y = y

    # 计算表头高度（固定）
    header_height = TABLE_ROW_HEIGHT

    # 计算所有数据行的真实高度（基于文本换行情况）
    row_heights = []
    for row in data:
        max_line_count = 1
        for i, cell in enumerate(row):
            # 按单元格文本类型计算换行次数
            if all(ord(c) < 128 for c in cell):  # 纯英文
                chars_per_line = int(col_widths[i] / (FONT_TABLE.size * 0.6))
                line_count = len(textwrap.wrap(cell, width=chars_per_line, break_long_words=False))
            else:  # 含中文
                chinese_width, _ = get_text_size(draw, "中", FONT_TABLE)
                chars_per_line = int(col_widths[i] / chinese_width) - 1
                line_count = len(textwrap.wrap(cell, width=chars_per_line))
            max_line_count = max(max_line_count, line_count)
        # 计算行高（文字高度+上下间距，确保不拥挤）
        row_height = max_line_count * (FONT_TABLE.size + 4) + 10
        row_heights.append(row_height)

    # 检查当前页是否能容纳表头+至少一行数据（避免表格跨页断裂）
    total_min_height = header_height + (row_heights[0] if row_heights else 0) + 20
    if current_y + total_min_height > HEIGHT - MARGIN:
        return None

    # 绘制表头（灰色背景+水平居中）
    draw.rectangle([x, current_y, x + TEXT_WIDTH, current_y + header_height], fill=(240, 240, 240))
    current_x = x
    for i, h in enumerate(header):
        text_width, _ = get_text_size(draw, h, FONT_TABLE)
        text_x = current_x + (col_widths[i] - text_width) / 2  # 水平居中
        draw.text((text_x, current_y + 15), h, font=FONT_TABLE, fill=TEXT_COLOR)
        current_x += col_widths[i]
    current_y += header_height

    # 绘制数据行（逐行处理，中英文自适应换行）
    for idx, (row, row_height) in enumerate(zip(data, row_heights)):
        if current_y + row_height > HEIGHT - MARGIN:
            return None  # 空间不足，提示换页

        # 绘制单元格边框
        draw.rectangle([x, current_y, x + TEXT_WIDTH, current_y + row_height], outline=(200, 200, 200), width=1)
        current_x = x

        for i, cell in enumerate(row):
            # 单元格文本换行处理
            if all(ord(c) < 128 for c in cell):  # 纯英文
                chars_per_line = int(col_widths[i] / (FONT_TABLE.size * 0.6))
                wrapped_lines = textwrap.wrap(cell, width=chars_per_line, break_long_words=False)
            else:  # 含中文
                chinese_width, _ = get_text_size(draw, "中", FONT_TABLE)
                chars_per_line = int(col_widths[i] / chinese_width) - 1
                wrapped_lines = textwrap.wrap(cell, width=chars_per_line)

            # 文字垂直居中
            total_line_height = len(wrapped_lines) * (FONT_TABLE.size + 4)
            line_y = current_y + (row_height - total_line_height) / 2

            for line in wrapped_lines:
                draw.text((current_x + 5, line_y), line, font=FONT_TABLE, fill=TEXT_COLOR)
                line_y += FONT_TABLE.size + 4

            current_x += col_widths[i]
        current_y += row_height

    return current_y


# --- 主生成函数 ---
def generate_article_reports():
    current_page = 1
    current_y = MARGIN
    img = Image.new('RGB', (WIDTH, HEIGHT), color=BACKGROUND_COLOR)
    draw = ImageDraw.Draw(img)

    def save_page():
        """保存当前页并初始化新页面"""
        nonlocal img, draw, current_page, current_y
        output_file_name = f"Pomeranian_Article_Report_{current_page}.png"
        output_path = os.path.join(OUTPUT_DIR, output_file_name)
        img.save(output_path)
        print(f"成功生成报告图片: {output_file_name}")

        # 初始化新页面
        current_page += 1
        current_y = MARGIN
        img = Image.new('RGB', (WIDTH, HEIGHT), color=BACKGROUND_COLOR)
        draw = ImageDraw.Draw(img)

    # 循环处理所有章节（支持跨页继续，避免内容断裂）
    section_idx = 0
    while section_idx < len(article_sections):
        section = article_sections[section_idx]
        section_type = section["type"]

        if section_type == "title":
            content = section["content"]
            # 检查标题是否溢出（预留下划线和间距）
            if current_y + FONT_TITLE.size + 40 > HEIGHT - MARGIN:
                save_page()
            # 绘制标题和下划线
            draw.text((MARGIN, current_y), content, font=FONT_TITLE, fill=TITLE_COLOR)
            current_y += FONT_TITLE.size + 20
            draw.line([(MARGIN, current_y), (WIDTH - MARGIN, current_y)], fill=TITLE_COLOR, width=3)
            current_y += 20
            section_idx += 1

        elif section_type == "subtitle":
            content = section["content"]
            if current_y + FONT_SUBTITLE.size + 15 > HEIGHT - MARGIN:
                save_page()
            draw.text((MARGIN, current_y), content, font=FONT_SUBTITLE, fill=TITLE_COLOR)
            current_y += FONT_SUBTITLE.size + 15
            section_idx += 1

        elif section_type == "text":
            content = section["content"]
            # 绘制文本并检查溢出
            new_y = draw_text_with_wrap(draw, content, MARGIN, current_y, FONT_TEXT, TEXT_WIDTH)
            if new_y is None:  # 溢出，换页后重新处理当前段落
                save_page()
            else:
                current_y = new_y + 15  # 段落间距
                section_idx += 1

        elif section_type == "table":
            header = section["header"]
            data = section["data"]
            cols_ratio = section["cols"]
            # 绘制表格并检查溢出
            new_y = draw_table(draw, header, data, MARGIN, current_y, cols_ratio)
            if new_y is None:  # 溢出，换页后重新处理当前表格
                save_page()
            else:
                current_y = new_y + 15  # 表格间距
                section_idx += 1

    # 保存最后一页
    save_page()


# --- 执行生成和打包 ---
if __name__ == "__main__":
    generate_article_reports()

    # 打包所有图片报告（仅打包.png文件，保持压缩包整洁）
    with zipfile.ZipFile(ZIP_PATH, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, _, files in os.walk(OUTPUT_DIR):
            for file in files:
                if file.endswith(".png"):
                    file_path = os.path.join(root, file)
                    zipf.write(file_path, os.path.basename(file_path))  # 仅保留文件名，去除路径层级

    # 输出统计信息
    total_images = len([f for f in os.listdir(OUTPUT_DIR) if f.endswith('.png')])
    print(f"\n✅ 生成完成！共生成 {total_images} 张图片报告")
    print(f"\n📁 打包文件路径：{ZIP_PATH}")